﻿
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ToolUtil
{
    public partial class PubTextBox : TextBox
    {
        //设置Rect消息
        private const int EM_SETRECT = 179;
        //获取Rect消息
        private const int EM_GETRECT = 178;
        //粘贴消息
        private const int WM_PASTE = 0x0302;
        private const int WM_PAINT = 0xF;
        private string _emptyTextTip;
        private Color _emptyTextTipColor = Color.DarkGray;
        public PubTextBox()
        {
            InitializeComponent();
        }
        [DefaultValue("")]
        public string EmptyTextTip
        {
            get { return _emptyTextTip; }
            set
            {
                _emptyTextTip = value;
                base.Invalidate();
            }
        }
        [DefaultValue(typeof(Color), "DarkGray")]
        public Color EmptyTextTipColor
        {
            get { return _emptyTextTipColor; }
            set
            {
                _emptyTextTipColor = value;
                base.Invalidate();
            }
        }
        protected override void OnTextAlignChanged(EventArgs e)
        {
            base.OnTextAlignChanged(e);
            SetTextDispLayout();
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            //如果不允许回车 屏蔽回车 换行键值
            if (!AllowReturn
                && ((int)e.KeyChar == (int)Keys.Return || (int)e.KeyChar == (int)Keys.LineFeed))
            {
                e.Handled = true;
            }
            base.OnKeyPress(e);
        }
        
        /// <summary>
        /// 窗体处理消息主函数 处理粘贴及绘制消息
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            string str = "";
            bool flag = false;
            int i = 0;
            if (m.Msg == 0x0204)
                i++;
            if (!AllowReturn
                && m.Msg == WM_PASTE
                && System.Windows.Forms.Clipboard.ContainsText())
            {
                str = System.Windows.Forms.Clipboard.GetText();
                System.Windows.Forms.Clipboard.Clear();
                string nstr = str.Replace(char.ConvertFromUtf32((int)Keys.Return), "").Replace(char.ConvertFromUtf32((int)Keys.LineFeed), "");
                System.Windows.Forms.Clipboard.SetText(nstr);
                if (str.Length > 0) flag = true;
            }
            
            base.WndProc(ref m);
            if (m.Msg == WM_PAINT)
            {
                WmPaint(ref m);
            }
            if (flag)
            {
                flag = false;
                System.Windows.Forms.Clipboard.SetText(str);
                str = "";
            }
        }

        private void WmPaint(ref Message m)
        {
            using (Graphics graphics = Graphics.FromHwnd(base.Handle))
            {
                if (Text.Length == 0
                    && !string.IsNullOrEmpty(_emptyTextTip)
                    && !Focused)
                {
                    TextFormatFlags format =
                        TextFormatFlags.EndEllipsis |
                        TextFormatFlags.VerticalCenter;

                    if (RightToLeft == RightToLeft.Yes)
                    {
                        format |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
                    }

                    TextRenderer.DrawText(
                        graphics,
                        _emptyTextTip,
                        Font,
                        base.ClientRectangle,
                        _emptyTextTipColor,
                        format);
                }
            }
        }

        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, string lParam);

        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, ref Rectangle lParam);

        /// <summary>
        /// 尺寸变化时重新设置字体的显示位置居中
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            SetTextDispLayout();
        }

        /// <summary>
        /// 设置文本显示布局位置
        /// </summary>
        public void SetTextDispLayout()
        {
            if (Text == "")
                return;
            //當允許多行和禁止回車時，Paddin有效
            if (this.Multiline && (!AllowReturn))
            {
                Rectangle rect = new Rectangle();
                SendMessage(this.Handle, EM_GETRECT, (IntPtr)0, ref rect);
                //SizeF size = CreateGraphics().MeasureString(Text, Font);//垂直居中 計算文本高度
                //rect.Y = (int)(Height - size.Height) / 2 + TextPadding.Top;
                rect.Y = TextPadding.Top;
                rect.X = TextPadding.Left;
                rect.Height = Height;
                rect.Width = Width - TextPadding.Right - TextPadding.Left;
                SendMessage(this.Handle, EM_SETRECT, IntPtr.Zero, ref rect);
            }
        }
        

        /// <summary>
        /// 是否允许有回车
        /// </summary>
        [CategoryAttribute("設定"), DisplayName("允許回車"), DescriptionAttribute("配合內邊使用")]
        public bool AllowReturn { get; set; }

        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            SetTextDispLayout();
        }

        private Padding _textpadding = new Padding(1);
        /// <summary>
        /// Text Padding值  當允許多行和禁止回車時，Paddin有效
        /// </summary>
        [CategoryAttribute("設定"), DisplayName("內邊距"), DescriptionAttribute(" 當允許多行和禁止回車時，Paddin有效")]

        public Padding TextPadding { get { return _textpadding; } set { _textpadding = value; SetTextDispLayout(); } }

    }
}
